~ 雲端有雲端的規則 ~
我們今天來嘗試把 api 放到 AWS Lambda 上跑
首先先修改 lambda_function.py 加入以下函式:
import shioaji as sj
import json
def lambda_handler(event, context):
api_key = event['apiKey']
secret_key = event['secretKey']
if len(api_key) > 0 and len(api_key) > 0:
api = sj.Shioaji(simulation=True)
accounts = api.login(api_key, secret_key)
if len(accounts) > 1:
return {
'statusCode': 200,
'body': accounts[0].account_id
}
else:
return {
'statusCode': 404,
'body': accounts[0].account_id
}
else:
return {
'statusCode': 400,
'body': json.dumps('Bad Request')
}
新增 Dockerfile 如下:
FROM public.ecr.aws/lambda/python:3.11
# Copy requirements.txt
COPY requirements.txt ${LAMBDA_TASK_ROOT}
# Copy function code
COPY lambda_function.py ${LAMBDA_TASK_ROOT}
# Install the specified packages
RUN pip install -r requirements.txt
# Set the CMD to your handler (could also be done as a parameter override outside of the Dockerfile)
CMD [ "lambda_function.lambda_handler" ]
requirements.txt 新增一行:
shioaji
然後在本機端建置 image,由於此 image 與之前開發用的不同,我們使用另一個名字:
$ docker build --platform linux/amd64 --no-cache \
-f Dockerfile.dev \
-t marathon-sinotrade-lambda:latest .
可以在本機端測試:
$ docker run -p 9000:8080 marathon-sinotrade-lambda:latest
# open a new console
$ curl "http://localhost:9000/2015-03-31/functions/function/invocations" -d '{}'
{"errorMessage": "'apiKey'", "errorType": "KeyError", "requestId": "c62882fa-0892-4914-aaad-5d8f19c276eb", "stackTrace": [" File \"/var/task/lambda_function.py\", line 5, in lambda_handler\n api_key = event['apiKey']\n"]}%
接著把它丟到 AWS ECR 上面:
# query account id
$ aws sts get-caller-identity --query "Account" --output text
# login to ECR
$ aws ecr get-login-password \
--region ap-northeast-1 | docker login \
--username AWS \
--password-stdin <account_id>.dkr.ecr.ap-northeast-1.amazonaws.com
$ aws ecr create-repository \
--repository-name marathon-sinotrade-lambda \
--image-scanning-configuration scanOnPush=true \
--image-tag-mutability MUTABLE
$ docker tag marathon-sinotrade-lambda:latest \
<account_id>.dkr.ecr.ap-northeast-1.amazonaws.com/marathon-sinotrade-lambda:latest
$ docker push \
<account_id>.dkr.ecr.ap-northeast-1.amazonaws.com/marathon-sinotrade-lambda:latest
建立 lambda function(使用 Day7 建立的 execution role):
$ aws lambda create-function \
--function-name marathon-sinotrade-lambda \
--package-type Image \
--code ImageUri=<account_id>.dkr.ecr.ap-northeast-1.amazonaws.com/marathon-sinotrade-lambda:latest \
--role arn:aws:iam::<account_id>:role/marathon-lambda-ex
因為永豐 api 預設會寫檔而 lambda 會沒有寫入檔案的權限,需要加入以環境變數改變寫檔位置,還好 lambda 有 /tmp 暫存資料夾可以使用,另外預設 timeout 時間是 3 sec,我們把它改到 1 min (最長可以到 15 min):
$ aws lambda update-function-configuration \
--function-name marathon-sinotrade-lambda \
--timeout 60 \
--environment "Variables={SJ_CONTRACTS_PATH=/tmp,SJ_LOG_PATH=/tmp/shioaji.log}"
我們這是測試開發用,就不設定 vpc 了,一般來說建議設定,這隻 api 需要連外,也需要給 AWS 內部使用,建議是放在私有子網設定 NAT 連出去
預設不設定 vpc 是可以連外的,我們可以測試一下:
# payload.json
{
"apiKey":"XXX",
"secretKey":"XXX"
}
$ aws lambda invoke \
--function-name marathon-sinotrade-lambda \
--payload file://payload.json response.json
$ vi response.json
{"statusCode": 200, "body": <sino_account_id>}
現在我們可以改寫 lambda_handler(event, context) 來客製化我們的下單機啦!
這整個開發建置流程似乎還有需要改善的地方,總結這兩天的心得如下:
https://docs.aws.amazon.com/lambda/latest/dg/python-image.html#python-image-instructions
https://sinotrade.github.io/
https://docs.aws.amazon.com/cli/latest/reference/lambda/create-function.html